/**
 * 文   件  名：  AbstractSubject.java
 * 工   程  名：  EventUtil
 * 创建日期：  2015年1月26日 下午12:35:52
 * 创建作者：  杨  强 <281455776@qq.com>
 */
package event.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import event.IEventListener;
import event.Observable;

/**
 * 抽象主题
 * 
 * @author 杨 强
 *
 */
public class BaseSubject implements Observable {
    private static final Map<Class<? extends IEventListener>, List<IEventListener>> observes = new ConcurrentHashMap<Class<? extends IEventListener>, List<IEventListener>>();

    @SuppressWarnings("unchecked")
    @Override
    public void addEventListener(IEventListener listener) {
        if (listener == null) {
            return;
        }
        Class<? extends IEventListener> cls = listener.getClass();// 取得事件类
        Class<?>[] interfaces = cls.getInterfaces();// 取得事件接口
        for (Class<?> clz : interfaces) {
            // 实现事件接口,放入到对应事件的监听列表中
            if (IEventListener.class.isAssignableFrom(clz) && clz != IEventListener.class) {
                if (!observes.containsKey(clz)) {
                    observes.put((Class<? extends IEventListener>) clz, new ArrayList<IEventListener>());
                }
                List<IEventListener> obs = observes.get(clz);
                obs.add(listener);
            }
        }
    }

    @Override
    public void delEventListener(IEventListener listener) {
        if (listener == null) {
            return;
        }
        Class<? extends IEventListener> cls = listener.getClass();// 取得事件类
        Class<?>[] interfaces = cls.getInterfaces();// 取得事件接口
        for (Class<?> clz : interfaces) {
            // 实现事件接口,从对应事件监听列表中删除
            if (IEventListener.class.isAssignableFrom(clz) && clz != IEventListener.class) {
                List<IEventListener> obs = observes.get(clz);
                if (obs != null) {
                    obs.remove(listener);
                }
            }
        }
    }

    @Override
    public void notifyEventListeners(Class<? extends IEventListener> eventListener, Object... param) {
        if (eventListener == null) {
            return;
        }
        // 获取该事件所有的方法
        Method[] methods = eventListener.getDeclaredMethods();
        if (methods == null || methods.length < 1) {
            return;
        }
        List<IEventListener> obs = observes.get(eventListener);
        if (obs != null) {
            // 对注册到该事件上的所有监听者，触发他们的事件方法
            for (IEventListener listener : obs) {
                for (Method method : methods) {
                    try {
                        // 无参数，则不传参数
                        if (method.getParameterTypes().length < 1) {
                            method.invoke(listener);
                        } else {
                            method.invoke(listener, param);
                        }
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
